package com.uuah.server.endpoint;

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLDecoder;
import java.util.Properties;

import com.uuah.server.api.endpoint.IEndpointURI;
import com.uuah.server.api.endpoint.IEndpointURIBuilder;
import com.uuah.server.exception.endpoint.MalformedEndpointException;
import com.uuah.utils.PropertiesUtils;

/**
 * {@link UrlEndpointURIBuilder} is the default endpointUri strategy suitable
 * for most connectors
 *
 * <p>
 * update record:updator，update time，update content and version
 * </p>
 *
 * @author <a href="jonny_quan@hotmail.com">jonny</a>
 * @date 2009 2009-3-27 下午01:36:40
 * @version 1.0.0
 */
public abstract class AbstractEndpointURIBuilder implements IEndpointURIBuilder {
	protected String address;
	protected String endpointName;
	protected String connectorName;
	protected String transformers;
	protected String responseTransformers;
	protected String userInfo;

	public IEndpointURI build(URI uri) throws MalformedEndpointException {
		Properties props = getPropertiesForURI(uri);
		String replaceAddress = null;
		if (address != null) {
			replaceAddress = address;
			setEndpoint(uri, props);
			address = replaceAddress;
		} else {
			setEndpoint(uri, props);
		}

		IEndpointURI ep = new UuahEndpointURI(address, endpointName,
				connectorName, transformers, responseTransformers, props, uri,
				userInfo);
		address = null;
		endpointName = null;
		connectorName = null;
		transformers = null;
		responseTransformers = null;
		return ep;
	}

	protected abstract void setEndpoint(URI uri, Properties props)
			throws MalformedEndpointException;

	protected Properties getPropertiesForURI(URI uri)
			throws MalformedEndpointException {
		Properties properties = PropertiesUtils
				.getPropertiesFromQueryString(uri.getQuery());

		String tempEndpointName = (String) properties
				.get(IEndpointURI.PROPERTY_ENDPOINT_NAME);
		if (tempEndpointName != null) {
			this.endpointName = tempEndpointName;
		}
		// override the endpointUri if set
		String endpoint = (String) properties
				.get(IEndpointURI.PROPERTY_ENDPOINT_URI);
		if (endpoint != null) {
			this.address = endpoint;
			address = decode(address, uri);
		}

		String cnnName = (String) properties
				.get(IEndpointURI.PROPERTY_CONNECTOR_NAME);
		if (cnnName != null) {
			this.connectorName = cnnName;
		}

		transformers = (String) properties
				.get(IEndpointURI.PROPERTY_REQUEST_TRANSFORMERS);
		if (transformers != null) {
			transformers = transformers.replaceAll(" ", ",");
		}
		responseTransformers = (String) properties
				.get(IEndpointURI.PROPERTY_RESPONSE_TRANSFORMERS);
		if (responseTransformers != null) {
			responseTransformers = responseTransformers.replaceAll(" ", ",");
		}
		userInfo = uri.getUserInfo();
		return properties;
	}

	private String decode(String string, URI uri)
			throws MalformedEndpointException {
		try {
			return URLDecoder.decode(string, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			throw new MalformedEndpointException(uri.toString(), e);
		}
	}
}
